// @Date         2021-11-04
// @Author       Aaron Zhang
// @Description
// @FileName      timeout.go

package middlewares

import (
	"context"
	"fmt"
	"log"
	"net/http"
	"runtime/debug"
	"time"
	_const "zin/framework/const"
	"zin/framework/gin"
)

func Timeout(c *gin.Context) {
	panicChan := make(chan interface{}, 0)
	finishChan := make(chan struct{}, 0)

	ctx, cancelFunc := context.WithTimeout(c.Request.Context(), time.Second*time.Duration(_const.Timeout))
	defer cancelFunc()

	//多协成，捕获异常
	go func() {
		defer func() {
			if err := recover(); err != nil {
				panicChan <- err
			}
		}()
		c.Next()
		finishChan <- struct{}{}
	}()
	c.Request.WithContext(ctx)

	select {

	case p := <-panicChan:
		fmt.Printf("发生错误：%s, \n\n trace : %v", p, string(debug.Stack()))
		c.AbortWithStatusJSON(http.StatusOK, gin.H{"msg": "系统发生错误"})
	case <-ctx.Done():
		c.AbortWithStatusJSON(http.StatusOK, map[string]interface{}{"error": "timeout"})
	case <-finishChan:
		log.Println("request OK")
	}

}
